// 迭代器设计模式
// 对外提供统一的遍历接口, 让外部不需要去关心数据内部的结构是什么样子的
// 数据
const todos = {
  life: ['吃饭', '睡觉', '打豆豆'],
  learn: ['语文', '数学', '英语'],
  work: ['摸鱼'],
  // 添加一个遍历接口!
  // 有数据结构的限制
  each: function (callback) {
    const all = [].concat(this.life, this.learn, this.work)
    for (const i of all) {
      callback(i)
    }
  },
  // 添加一个可迭代接口!
  // 适用于任何数据结构
  [Symbol.iterator]: function () {
    const all = [...this.life, ...this.learn, ...this.work]
    // 实现并return一个next方法
    let index = 0
    return {
      next: function () {
        return {
          value: all[index],
          done: index++ >= all.length,
        }
      },
    }
  },
}
// 呈现数据 调用者 传统如果原来的对象增加一维 遍历需要增加一个循环
for (const i of todos.life) {
  console.log(i)
}
for (const i of todos.learn) {
  console.log(i)
}
for (const i of todos.work) {
  console.log(i)
}
console.log('-----------------------------------')
// 如果不用关心调用对象的内部结构 也不用关心调用对象内部改变造成的影响
todos.each(function (i) {
  console.log(i)
})
console.log('-----------------------------------')
for (const i of todos) {
  console.log(i)
}

// 利用生成器实现

// 发号器
// 自增ID
function* createIdMaker() {
  let id = 1
  while (true) {
    // 不需要担心死循环因为yield直接停
    yield id++
  }
}

const idMaker = createIdMaker()
console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)
console.log(idMaker.next().value)
// 1
// 2
// 3
// 4
// 5
// -------------------------------------------------------
// 实现iterator方法
const todos = {
  life: ['吃饭', '睡觉', '打豆豆'],
  learn: ['语文', '数学', '英语'],
  work: ['摸鱼'],

  // 添加一个可迭代接口!
  // 适用于任何数据结构
  [Symbol.iterator]: function* () {
    const all = [...this.life, ...this.learn, ...this.work]
    // yield本身就有next方法 秒啊
    for (const i of all) {
      yield i
    }
  },
}
for (const i of todos) {
  console.log(i)
}
// 吃饭
// 睡觉
// 打豆豆
// 语文
// 数学
// 英语
// 摸鱼

// 生成器让iterable的内部实现更简单了 直接for..of遍历所有数据然后yield这个数据(给这个数据绑定一个next())
